package algo;

import model.tsp.Problem;
import model.tsp.Solution;
import util.SelectUtils;

import java.util.Arrays;
import java.util.List;

/**
 * weighted neighborhood operator
 */
public class LocalSearch4 extends LocalSearch {

    public LocalSearch4(Problem problem) {
        super(problem);
    }

    @Override
    protected Solution localSearch(Solution solution) {
        int localSearchCnt = 18000;
        double lambda = 0.2;
        Solution bestSolution = solution.copy();//最优解
        Solution currentSolution = solution.copy();//当前解

        double[] weights = new double[6];//算子权重
        Arrays.fill(weights, 1.0);

        // 局部搜索过程，搜索邻域k中的较优解
        // 每个操作算子随机变换一次
        for (int i = 0; i < localSearchCnt; i++) {
            List<Integer> newX;
            int k = SelectUtils.rouletteSelectOperator(weights, random);

            if (k == 0) {
                newX = neighborhoodOperator1(currentSolution.getPermutation());
            } else if (k == 1) {
                newX = neighborhoodOperator2(currentSolution.getPermutation());
            } else if (k == 2) {
                newX = neighborhoodOperator3(currentSolution.getPermutation());
            } else if (k == 3) {
                newX = neighborhoodOperator4(currentSolution.getPermutation());
            } else if (k == 4) {
                newX = neighborhoodOperator5(currentSolution.getPermutation());
            } else if (k == 5) {
                newX = neighborhoodOperator6(currentSolution.getPermutation());
            } else {
                throw new RuntimeException("超出neighborhood邻域集合长度: " + k);
            }

            Solution newSolution = new Solution(newX, calculateFitness(newX));
            if (newSolution.getCost() < bestSolution.getCost()) {//优于历史最优解
                bestSolution = newSolution.copy();
                currentSolution = newSolution.copy();
                weights[k] = weights[k] + lambda * (8 - weights[k]);//更新算子权重
            } else if (newSolution.getCost() < currentSolution.getCost()) {//优于当前解
                currentSolution = newSolution.copy();
                weights[k] = weights[k] + lambda * (4 - weights[k]);
            } else {
                weights[k] = weights[k] + lambda * (2 - weights[k]);
            }
        }

        return bestSolution;
    }




}
